package cn.yuanqiao.web.controller.activiti;


import cn.yuanqiao.activiti.domain.ActConForm;
import cn.yuanqiao.activiti.domain.dto.ProcessDefinitionDTO;
import cn.yuanqiao.activiti.service.IActConFormService;
import cn.yuanqiao.activiti.service.IProcessDefinitionService;

import cn.yuanqiao.archive.storeRoom.service.InitializationService;
import cn.yuanqiao.common.core.controller.BaseController;
import cn.yuanqiao.common.core.domain.AjaxResult;
import cn.yuanqiao.common.core.domain.R;
import cn.yuanqiao.common.core.page.PageDomain;
import cn.yuanqiao.common.core.page.TableDataInfo;
import cn.yuanqiao.common.core.page.TableSupport;
import cn.yuanqiao.common.annotation.Log;
import cn.yuanqiao.common.domain.YqTable;
import cn.yuanqiao.common.enums.BusinessType;
import cn.yuanqiao.common.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityImpl;
import org.activiti.engine.repository.Deployment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;


@RestController
@RequestMapping("/activiti/processDefinition")
public class ProcessDefinitionController extends BaseController {

    @Autowired
    private IProcessDefinitionService processDefinitionService;

    @Autowired
    private InitializationService initializationService;

    @Autowired
    private IActConFormService actConFormService;


    /**
     * 获取流程定义集合
     *
     * @param processDefinition
     * @return
     */
    @GetMapping(value = "/list")
    public TableDataInfo list(ProcessDefinitionDTO processDefinition) {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        return getDataTable(processDefinitionService.selectProcessDefinitionList(processDefinition, pageDomain));

    }

    /**
     * 获取流程定义集合
     *
     * @param processDefinition
     * @return
     */
    @GetMapping(value = "/formList")
    public TableDataInfo formList(ProcessDefinitionDTO processDefinition) {
        List<YqTable> tableList = initializationService.getTableList();
        return getDataTable(tableList);

    }

    /**
     * 获取流程
     * @return
     */
    @GetMapping(value = "/getDefinitions/{instanceId}")
    public AjaxResult getDefinitionsByInstanceId(@PathVariable("instanceId") String instanceId){
        return AjaxResult.success(processDefinitionService.getDefinitionsByInstanceId(instanceId));
    }

    /**
     * 删除流程定义
     *
     * @param deploymentId
     * @return
     */
    @Log(title = "流程定义管理", businessType = BusinessType.DELETE)
    @DeleteMapping(value = "/remove/{deploymentId}")
    public AjaxResult delDefinition(@PathVariable("deploymentId") String deploymentId) {
        return toAjax(processDefinitionService.deleteProcessDefinitionById(deploymentId));
    }

    /**
     * 上传并部署流程定义
     *
     * @param file
     * @return
     * @throws IOException
     */
    @Log(title = "流程定义管理", businessType = BusinessType.IMPORT)
    @PostMapping(value = "/uploadStreamAndDeployment")
    public AjaxResult uploadStreamAndDeployment(@RequestParam("file") MultipartFile file) throws IOException {
        processDefinitionService.uploadStreamAndDeployment(file);
        return AjaxResult.success();

    }

    /**
     * 启动挂起流程流程定义
     *
     * @param processDefinition
     * @return
     */
    @Log(title = "流程定义管理", businessType = BusinessType.UPDATE)
    @PostMapping("/suspendOrActiveApply")
    @ResponseBody
    public AjaxResult suspendOrActiveApply(@RequestBody ProcessDefinitionDTO processDefinition) {
        processDefinitionService.suspendOrActiveApply(processDefinition.getId(), processDefinition.getSuspendState());
        return AjaxResult.success();
    }

    /**
     * 上传流程流程定义
     *
     * @param multipartFile
     * @return
     * @throws IOException
     */
    @Log(title = "流程定义管理", businessType = BusinessType.IMPORT)
    @PostMapping(value = "/upload")
    public AjaxResult upload(@RequestParam("processFile") MultipartFile multipartFile) throws IOException {

        if (!multipartFile.isEmpty()) {
            String fileName = processDefinitionService.upload(multipartFile);
            return AjaxResult.success("操作成功", multipartFile.getBytes());

        }
        return AjaxResult.error("不允许上传空文件！");
    }


    /**
     * 通过stringBPMN添加流程定义
     *
     * @param stringBPMN
     * @return
     */
    @PostMapping(value = "/addDeploymentByString")
    public AjaxResult addDeploymentByString(@RequestParam("stringBPMN") String stringBPMN, @RequestParam("formId") String formId, HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        String token = Arrays.stream(cookies).filter(item -> item.getName().equals("Admin-Token")).findAny().get().getValue();
        Claims claims = JwtUtils.parseToken(token);
        String tenantCode = String.valueOf(claims.get("tenant_code"));
        System.out.println(tenantCode);
        System.out.println("==============================");
        Deployment deployment = processDefinitionService.addDeploymentByString(stringBPMN,tenantCode);
        String formCode = actConFormService.selectFormCodeByFormId(formId);
        String businessKey = null;
        try {
            //Field deployedArtifacts = deployment.getClass().getField("deployedArtifacts");
            Field declaredField = deployment.getClass().getDeclaredField("deployedArtifacts");
            declaredField.setAccessible(true);
            Map<Object,Object> deployedArtifactsMap = (HashMap<Object,Object>)declaredField.get(deployment);
            for (Object item : deployedArtifactsMap.keySet()) {
                List<ProcessDefinitionEntityImpl> list = (ArrayList<ProcessDefinitionEntityImpl>)deployedArtifactsMap.get(item);
                ProcessDefinitionEntityImpl processDefinitionEntity = list.get(0);
                String key = processDefinitionEntity.getKey();
                if (key!=null){
                    businessKey = key;
                }
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
            throw new ActivitiObjectNotFoundException("部署流程未找到流程Key变量");
        }
        actConFormService.insertActConForm(new ActConForm(deployment.getId(),businessKey,formId,formCode,tenantCode));
        return AjaxResult.success();

    }


    /**
     * 获取流程定义XML
     *
     * @param response
     * @param deploymentId
     * @param resourceName
     */
    @GetMapping(value = "/getDefinitionXML")
    public void getProcessDefineXML(HttpServletResponse response,
                                    @RequestParam("deploymentId") String deploymentId,
                                    @RequestParam("resourceName") String resourceName) throws IOException {

        processDefinitionService.getProcessDefineXML(response, deploymentId, resourceName);
    }


}
